/*
 * DbRow.cpp
 *
 *  Created on: 2018年1月3日
 *      Author: zhengboyuan
 */

#include "DbRow.h"
#include "TStringCast.h"
#include "CLog.h"
#include "SociType.h"



namespace db
{

bool DbRow::get(soci::row& row, size_t pos, int& value)
{
	bool done = true;

    try
    {
        soci::column_properties const& prop = row.get_properties(pos);
        if (prop.get_data_type() == soci::dt_integer)
        {
            value = row.get<int>(pos);
        }
        else if (prop.get_data_type() == soci::dt_long_long)
        {
            value = (int)row.get<long long>(pos);
        }
        else if (prop.get_data_type() == soci::dt_unsigned_long_long)
        {
            value = (int)row.get<unsigned long long>(pos);
        }
        else if (prop.get_data_type() == soci::dt_double)
        {
            value = (int)(row.get<double>(pos));
        }
        else if (prop.get_data_type() == soci::dt_string)
        {
            std::string str = row.get<std::string>(pos);
            comn::StringCast::toValue(str, value);
        }
        else if (prop.get_data_type() == soci::dt_date)
        {
            struct tm tmCur;
            memset(&tmCur, 0, sizeof(tmCur));
            tmCur = row.get<tm>(pos);
            value = (int)mktime(&tmCur);
        }
        else
        {
            done = false;
        }
    }
    catch (soci::soci_error& ex)
    {
        CLog::warning("DbRow::get. soci_error. %s\n", ex.what());
        done = false;
    }
    catch (std::exception& ex)
    {
        CLog::warning("DbRow::get. ex. %s\n", ex.what());
        done = false;
    }

	return done;
}

bool DbRow::get(soci::row& row, size_t pos, int64_t& value)
{
	bool done = true;
	try
	{
		soci::column_properties const& prop = row.get_properties(pos);
		if (prop.get_data_type() == soci::dt_integer)
		{
			value = row.get<int>(pos);
		}
        else if (prop.get_data_type() == soci::dt_long_long)
        {
            value = (int64_t)row.get<long long>(pos);
        }
		else if (prop.get_data_type() == soci::dt_unsigned_long_long)
		{
			value = row.get<uint64_t>(pos);
		}
		else if (prop.get_data_type() == soci::dt_double)
		{
			value = (int64_t)(row.get<double>(pos));
		}
		else if (prop.get_data_type() == soci::dt_string)
		{
			std::string str = row.get<std::string>(pos);
			comn::StringCast::toValue(str, value);
		}
        else if (prop.get_data_type() == soci::dt_date)
        {
            struct tm tmCur;
            memset(&tmCur, 0, sizeof(tmCur));
            tmCur = row.get<tm>(pos);
            value = mktime(&tmCur);
        }
		else
		{
			done = false;
		}
	}
    catch (soci::soci_error& ex)
    {
        CLog::warning("DbRow::get. soci_error. %s\n", ex.what());
        done = false;
    }
    catch (std::exception& ex)
    {
        CLog::warning("DbRow::get. ex. %s\n", ex.what());
        done = false;
    }
	
	return done;
}

bool DbRow::get(soci::row& row, size_t pos, std::string& value)
{
	bool done = true;
	try
	{
		if (isNull(row, pos))
		{
			value.clear();
			return done;
		}

		soci::column_properties const& prop = row.get_properties(pos);
		if (prop.get_data_type() == soci::dt_long_long)
		{
			value = comn::StringCast::toString(row.get<long long>(pos));
		}
		else if (prop.get_data_type() == soci::dt_unsigned_long_long)
		{
			value = comn::StringCast::toString(row.get<unsigned long long>(pos));
		}
		else if (prop.get_data_type() == soci::dt_double)
		{
			value = comn::StringCast::toString(row.get<double>(pos));
		}
		else if (prop.get_data_type() == soci::dt_integer)
		{
			value = comn::StringCast::toString(row.get<int>(pos));
		}
		else if (prop.get_data_type() == soci::dt_date)
		{
            struct tm tmCur;
            memset(&tmCur, 0, sizeof(tmCur));
            tmCur = row.get<tm>(pos);
            char buffer[64] = { 0 };
            strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tmCur);
            value = buffer;
		}
        else if (prop.get_data_type() == soci::dt_string)
        {
			if (isNull(row, pos))
			{
				value = std::string();
			}
			else
			{
				value = row.get<std::string>(pos);
			}
        }
		else
		{
			done = false;
		}
	}
    catch (soci::soci_error& ex)
    {
        CLog::warning("DbRow::get. soci_error. %s\n", ex.what());
        done = false;
    }
    catch (std::exception& ex)
    {
        CLog::warning("DbRow::get. ex. %s\n", ex.what());
        done = false;
    }
	
	return done;
}

bool DbRow::get(soci::row& row, size_t pos, double& value)
{
	bool done = true;
	try
	{
		if (isNull(row, pos))
		{
			value = 0;
			return done;
		}

		soci::column_properties const& prop = row.get_properties(pos);
        if (prop.get_data_type() == soci::dt_double)
        {
            value = row.get<double>(pos);
        }
		else if (prop.get_data_type() == soci::dt_long_long)
		{
			value = (double)row.get<long long>(pos);
		}
		else if (prop.get_data_type() == soci::dt_unsigned_long_long)
		{
			value = (double)row.get<unsigned long long>(pos);
		}
		else if (prop.get_data_type() == soci::dt_integer)
		{
			value = row.get<int>(pos);
		}
		else if (prop.get_data_type() == soci::dt_string)
		{
			std::string str = row.get<std::string>(pos);
			comn::StringCast::toValue(str, value);
		}
        else if (prop.get_data_type() == soci::dt_date)
        {
            struct tm tmCur;
            memset(&tmCur, 0, sizeof(tmCur));
            tmCur = row.get<tm>(pos);
            value = (double)mktime(&tmCur);
        }
		else
		{
			done = false;
		}
	}
    catch (soci::soci_error& ex)
    {
        CLog::warning("DbRow::get. soci_error. %s\n", ex.what());
        done = false;
    }
    catch (std::exception& ex)
    {
        CLog::warning("DbRow::get. ex. %s\n", ex.what());
        done = false;
    }
	return done;
}

bool DbRow::getTime(soci::row& row, size_t pos, time_t& value)
{
	bool done = true;
	try
	{
		struct tm t = row.get<tm>(pos);
        t.tm_isdst = 0;
        if (t.tm_year < 0)
        {
            t.tm_year = 100;
        }

        value = mktime(&t);
	}
    catch (soci::soci_error& ex)
    {
        CLog::warning("DbRow::getTime. soci_error. %s\n", ex.what());
        done = false;
    }
    catch (std::exception& ex)
    {
        CLog::warning("DbRow::getTime. ex. %s\n", ex.what());
        done = false;
    }
	return done;
}

bool DbRow::get(soci::row& row, const std::string& name, int& value)
{
	bool done = true;
	try
	{
		soci::column_properties const& prop = row.get_properties(name);
        if (prop.get_data_type() == soci::dt_integer)
        {
            value = row.get<int>(name);
        }
		else if (prop.get_data_type() == soci::dt_long_long)
		{
			value = (int)row.get<long long>(name);
		}
		else if (prop.get_data_type() == soci::dt_unsigned_long_long)
		{
			value = (int)row.get<unsigned long long>(name);
		}
		else if (prop.get_data_type() == soci::dt_double)
		{
			value = (int)(row.get<double>(name));
		}
		else if (prop.get_data_type() == soci::dt_string)
		{
			std::string str = row.get<std::string>(name);
			comn::StringCast::toValue(str, value);
		}
        else if (prop.get_data_type() == soci::dt_date)
        {
            struct tm tmCur;
            memset(&tmCur, 0, sizeof(tmCur));
            tmCur = row.get<tm>(name);
            value = (int)mktime(&tmCur);
        }
		else
		{
			done = false;
		}
	}
    catch (soci::soci_error& ex)
    {
        CLog::warning("DbRow::get. soci_error. %s\n", ex.what());
        done = false;
    }
    catch (std::exception& ex)
    {
        CLog::warning("DbRow::get. ex. %s\n", ex.what());
        done = false;
    }
	
	return done;
}

bool DbRow::get(soci::row& row, const std::string& name, int64_t& value)
{
	bool done = true;
	try
	{
		soci::column_properties const& prop = row.get_properties(name);
        if (prop.get_data_type() == soci::dt_long_long)
        {
            //value = row.get<int64_t>(name);
			value = (int64_t)row.get<long long>(name);
        }
		else if (prop.get_data_type() == soci::dt_integer)
		{
			value = row.get<int>(name);
		}
		else if (prop.get_data_type() == soci::dt_unsigned_long_long)
		{
			value = row.get<uint64_t>(name);
		}
		else if (prop.get_data_type() == soci::dt_double)
		{
			value = (int64_t)(row.get<double>(name));
		}
		else if (prop.get_data_type() == soci::dt_string)
		{
			std::string str = row.get<std::string>(name);
			comn::StringCast::toValue(str, value);
		}
        else if (prop.get_data_type() == soci::dt_date)
        {
            struct tm tmCur;
            memset(&tmCur, 0, sizeof(tmCur));
            tmCur = row.get<tm>(name);
            value = mktime(&tmCur);
        }
		else
		{
			done = false;
		}
	}
    catch (soci::soci_error& ex)
    {
        CLog::warning("DbRow::get. name: %s, soci_error. %s\n", name.c_str(), ex.what());
        done = false;
    }
    catch (std::exception& ex)
    {
        CLog::warning("DbRow::get. name: %s, ex. %s\n", name.c_str(), ex.what());
        done = false;
    }
	return done;
}

bool DbRow::get(soci::row& row, const std::string& name, std::string& value)
{
	bool done = true;
	try
	{
		soci::column_properties const& prop = row.get_properties(name);
        if (prop.get_data_type() == soci::dt_string)
        {
            value = row.get<std::string>(name);
        }
		else if (prop.get_data_type() == soci::dt_long_long)
		{
			value = comn::StringCast::toString(row.get<long long>(name));
		}
		else if (prop.get_data_type() == soci::dt_unsigned_long_long)
		{
			value = comn::StringCast::toString(row.get<unsigned long long>(name));
		}
		else if (prop.get_data_type() == soci::dt_double)
		{
			value = comn::StringCast::toString(row.get<double>(name));
		}
		else if (prop.get_data_type() == soci::dt_integer)
		{
			value = comn::StringCast::toString(row.get<int>(name));
		}
        else if (prop.get_data_type() == soci::dt_date)
        {
            struct tm tmCur;
            memset(&tmCur, 0, sizeof(tmCur));
            tmCur = row.get<tm>(name);
            char buffer[64] = { 0 };
            strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tmCur);
            value = buffer;
        }
		else
		{
			done = false;
		}
	}
    catch (soci::soci_error& ex)
    {
        CLog::warning("DbRow::get. soci_error. %s\n", ex.what());
        done = false;
    }
    catch (std::exception& ex)
    {
        CLog::warning("DbRow::get. ex. %s\n", ex.what());
        done = false;
    }
	
	return done;
}

bool DbRow::get(soci::row& row, const std::string& name, double& value)
{
	bool done = true;
	try
	{
		soci::column_properties const& prop = row.get_properties(name);
        if (prop.get_data_type() == soci::dt_double)
        {
            value = row.get<double>(name);
        }
		else if (prop.get_data_type() == soci::dt_long_long)
		{
			value = (double)row.get<long long>(name);
		}
		else if (prop.get_data_type() == soci::dt_unsigned_long_long)
		{
			value = (double)row.get<unsigned long long>(name);
		}
		else if (prop.get_data_type() == soci::dt_integer)
		{
			value = row.get<int>(name);
		}
		else if (prop.get_data_type() == soci::dt_string)
		{
			std::string str = row.get<std::string>(name);
			comn::StringCast::toValue(str, value);
		}
        else if (prop.get_data_type() == soci::dt_date)
        {
            struct tm tmCur;
            memset(&tmCur, 0, sizeof(tmCur));
            tmCur = row.get<tm>(name);
            value = (double)mktime(&tmCur);
        }
		else
		{
			done = false;
		}
	}
    catch (soci::soci_error& ex)
    {
        CLog::warning("DbRow::get. soci_error. %s\n", ex.what());
        done = false;
    }
    catch (std::exception& ex)
    {
        CLog::warning("DbRow::get. ex. %s\n", ex.what());
        done = false;
    }
	return done;
}

bool DbRow::getTime(soci::row& row, const std::string& name, time_t& value)
{
	bool done = true;
	try
	{
		struct tm t = row.get<tm>(name);
        t.tm_isdst = 0;
        if (t.tm_year < 0)
        {
            t.tm_year = 100;
        }

        value = mktime(&t);
	}
    catch (soci::soci_error& ex)
    {
        CLog::warning("DbRow::getTime. soci_error. %s\n", ex.what());
        done = false;
    }
    catch (std::exception& ex)
    {
        CLog::warning("DbRow::getTime. ex. %s\n", ex.what());
        done = false;
    }
	return done;
}

bool DbRow::isNull(soci::row& row, size_t pos)
{
	soci::indicator ind = row.get_indicator(pos);
	return (ind == soci::i_null || ind == soci::i_truncated);
}



DbRow::DbRow(soci::row& row):
		m_row(row)
{
}

DbRow::~DbRow()
{
}

soci::row& DbRow::get()
{
	return m_row;
}

bool DbRow::get(size_t pos, int& value)
{
	return get(m_row, pos, value);
}

bool DbRow::get(size_t pos, int64_t& value)
{
	return get(m_row, pos, value);
}

bool DbRow::get(size_t pos, std::string& value)
{
	return get(m_row, pos, value);
}

bool DbRow::get(size_t pos, double& value)
{
	return get(m_row, pos, value);
}

bool DbRow::getTime(size_t pos, time_t& value)
{
	return getTime(m_row, pos, value);
}


bool DbRow::get(const std::string& name, int& value)
{
	return get(m_row, name, value);
}

bool DbRow::get(const std::string& name, int64_t& value)
{
	return get(m_row, name, value);
}

bool DbRow::get(const std::string& name, std::string& value)
{
	return get(m_row, name, value);
}

bool DbRow::get(const std::string& name, double& value)
{
	return get(m_row, name, value);
}

bool DbRow::getTime(const std::string& name, time_t& value)
{
	return getTime(m_row, name, value);
}


int DbRow::opt(size_t pos, int value)
{
	get(m_row, pos, value);
	return value;
}

int64_t DbRow::opt(size_t pos, int64_t value)
{
	get(m_row, pos, value);
	return value;
}

std::string DbRow::opt(size_t pos, const std::string& value)
{
	std::string str(value);
	get(m_row, pos, str);
	return str;
}

double DbRow::opt(size_t pos, double value)
{
	get(m_row, pos, value);
	return value;
}

time_t DbRow::optTime(size_t pos, time_t value)
{
	getTime(m_row, pos, value);
	return value;
}

int DbRow::opt(const std::string& name, int value)
{
	get(m_row, name, value);
	return value;
}

int64_t DbRow::opt(const std::string& name, int64_t value)
{
	get(m_row, name, value);
	return value;
}

std::string DbRow::opt(const std::string& name, const std::string& value)
{
	std::string str(value);
	get(m_row, name, str);
	return str;
}

double DbRow::opt(const std::string& name, double value)
{
	get(m_row, name, value);
	return value;
}

time_t DbRow::optTime(const std::string& name, time_t value)
{
	getTime(m_row, name, value);
	return value;
}

bool DbRow::isNull(size_t pos)
{
    soci::indicator ind = m_row.get_indicator(pos);
    return ind == soci::i_null || ind == soci::i_truncated;
}

size_t DbRow::size() const
{
    return m_row.size();
}

std::string DbRow::getName(size_t idx) const
{
    soci::column_properties const& properties = m_row.get_properties(idx);
    std::string name = properties.get_name();
    return name;
}

DataType DbRow::getType(size_t idx) const
{
    soci::indicator ind = m_row.get_indicator(idx);
    if (ind == soci::i_null || ind == soci::i_truncated)
    {
        return DT_NULL;
    }

    soci::column_properties const& properties = m_row.get_properties(idx);
    return (DataType)properties.get_data_type();
}



} /* namespace db */
